<?php
/**
 * Name: 消息服务.
 * User: 董坤鸿
 * Date: 2016/10/12
 * Time: 14:25
 */

namespace App\Services;

use App\Models\AcceptRecord;
use App\Models\MessageError;
use App\Models\MessageLog;
use App\Models\Project;
use App\Models\WxClient;
use App\Models\Customer;
use App\Plugins\Plugin;
use App\Plugins\Wechat\Messages;
use App\Plugins\Wechat\SETTING;
use Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use MongoDB\BSON\Regex;

class WxClientService
{
    /**
     * 获取客户端Uin
     * @param null $_user
     * @return mixed
     */
    public function getClientsUin($_user = null)
    {
        $user = request()->user();
        $clientUins = Cache::remember("wx:ids:{$user->id}", 30, function () use ($user) {
            $projects = Project::where(['users' => $user->id])->get(['title', 'wx_id']);
            $ids = $projects->pluck('wx_id')->flatten()->all();
            return WxClient::whereIn('_id', $ids)->get()->pluck('uin')->all();
        });
        return $clientUins;
    }

    /**
     * 聊天历史记录
     * @param $uin
     * @param $customer
     * @param $filter
     * @param $pagnation
     * @return array
     */
    public function getMessageList($uin, $customer, $filter, $pagnation)
    {
        //查询条件
        if ($customer) {
            $account = array_get($customer, 'socialInfo.wechat.account', '');
            $nickName = array_get($customer, 'socialInfo.wechat.nickName', '');
        }
        //搜索内容
        $content = array_get($filter, 'content', '');
        $type = $content ? ['text_msg'] : SETTING::MAP_MSG_TYPE;
        $filters = [
            'type' => ['$in' => $type],
            '$or' => [['to' => ['$in' => [$account, $nickName]]], ['from' => ['$in' => [$account, $nickName]]]],
            'content' => new \MongoDB\BSON\Regex("$content", 'gi'),
        ];
        $messageHandler = new Messages($uin);
        $messages = $messageHandler->getMessages($filters, array_get($pagnation, 'limit', 20), array_get($pagnation, 'skip', 0));
        foreach ($messages['list'] as $key => $value) {
            if (isset($value['from'])) {
                $customer = Customer::where('socialInfo.wechat.account', $value->from)
                    ->orWhere('socialInfo.wechat.nickName', $value->from)
                    ->first();
                $messages['list'][$key]['from'] = $customer->id;
            } elseif (isset($value['to'])) {
                $customer = Customer::where('socialInfo.wechat.account', $value->to)
                    ->orWhere('socialInfo.wechat.nickName', $value->to)
                    ->first();
                $messages['list'][$key]['to'] = $customer->id;
            }
        }
        return $messages;
    }

    /**
     * 取出消息
     * @param null $time 时间
     * @return array
     */
    public function getMessages($time = null)
    {
        $user = request()->user();
        $cache_key = "{$user->id}:preReadTime";
        $preReadTime = is_null($time) ? Cache::get($cache_key, $time) : $time; // todo debug
        $clientUins = $this->getClientsUin();
        $contacts = [];
        $messages = [];
        $createTime = '';
        foreach ($clientUins as $clientUin) {
            $messageHandler = new Messages($clientUin);
            foreach ($messageHandler->messages($preReadTime) as $msg) {
                if (empty($msg)) continue;
                if (isset($msg->type) && $msg->type === SETTING::VERIFY_MSG) {
                    array_push($contacts, $msg->contact);
                } else {
                    //account、nickName替换为customer_id
                    if (!isset($msg->from)) continue;
                    $customer = Customer::where('socialInfo.wechat.account', $msg->from)
                        ->orWhere('socialInfo.wechat.nickName', $msg->from)->first();
                    if (is_null($customer)) continue;
                    $msg->from = $customer->id;
                    if (AcceptRecord::isAcceptByUser($customer->id, $user->id)) {
                        array_push($messages, $msg);
                    }
                    //取出最大的创建时间
                    $createTime = $createTime < ($msg->createTime) ? $msg->createTime : $createTime;
                }
            }
        }

        if (count($contacts) > 0 OR count($messages) > 0) {
            Cache::forever($cache_key, $time); // todo debug
        }

        $lastTime = $messages ? $createTime : time();   //处理lastTime
        $messageErrors = MessageError::where(['_v' => 0, 'user_id' => $user->id])->whereIn('clientUin', $clientUins)->get()->toArray();
        $messages = array_merge($messages, $messageErrors);
        foreach ($messageErrors as $v) {
            MessageError::where('_id', $v['_id'])->update(['_v' => 1]);
        }
        return compact('contacts', 'messages', 'lastTime');
    }

    /**
     * 验证消息
     * @param $message
     * @return array|bool
     */
    public function checkMessage(&$message)
    {
        //先检查字段是否存在
        if (empty($message['to']) || empty($message['type']) || empty($message['content']) || !is_numeric($message['clientUin'])) {
            return false;
        }
        $message['createdTime'] = time();   //创建时间
        $user = request()->user();
        //创建记录, 并记录发消息的人
        /** @var MessageLog $msgLog */
        $msgLog = MessageLog::create(array_merge($message, ['user_id' => $user->id]));
        if (!empty($message['isGroup']) && $message['isGroup'] == true) {
            $to = explode(',', $message['to']);
            $groups = [];
            foreach ($to as $value) {
                $message['to'] = $value;
                $result = $this->getReplaceTo($message, $msgLog, $user);
                if ($result) {
                    array_push($groups, $result);
                }
            }
            return $groups;
        } else {
            return $this->getReplaceTo($message, $msgLog, $user);
        }

    }

    /**
     * 替换TO为account或nickName
     * @param $message
     * @param $msgLog
     * @param $user
     * @return bool
     */
    public function getReplaceTo(&$message, $msgLog, $user)
    {
        $clientUin = $message['clientUin']; //Uin
        $from = $message['to'];   //取出客户ID
        //判断是否存在该客户
        $customer = Customer::find($message['to']);
        if (is_null($customer)) {
            $msgLog->result = false;
            $msgLog->save();
            $content = "客户不存在。";
            $this->messageError($content, $clientUin, $from);
            return false;
        }
        //验证消息是否为该客户认领的
        if (!AcceptRecord::isAcceptByUser($customer->id, $user->id)) {
            $msgLog->result = false;
            $msgLog->save();
            $content = "您当前的操作权限不够，不能与该客户聊天。";
            $this->messageError($content, $clientUin, $from);
            return false;
        }

        //account或nickName是否存在
        $message['to'] = array_get($customer->socialInfo, 'wechat.account', array_get($customer->socialInfo, 'wechat.nickName', ''));
        if (empty($message['to'])) {
            $msgLog->result = false;
            $msgLog->save();
            $content = "该客户不存在，不能聊天。";
            $this->messageError($content, $clientUin, $from);
            return false;
        } else {
            $message['clientId'] = $msgLog->id; // 将系统生成的消息ID放入消息包中
            $msgLog->result = true;
            $msgLog->save();
            return $message;
        }
    }

    /**
     * 处理错误消息
     * @param $content
     * @param $clientUin
     * @param $from
     */
    public function messageError(&$content, $clientUin, $from)
    {
        $user = request()->user();
        $messageError['clientUin'] = $clientUin;
        $messageError['msgId'] = (microtime(true) * 10000) . rand(1000, 9999);
        $messageError['from'] = $from;
        $messageError['content'] = $content;
        $messageError['createTime'] = time() + 1;
        $messageError['type'] = SETTING::SYS_MSG;
        $messageError['_v'] = 0;
        MessageError::create(array_merge($messageError, ['user_id' => $user->id]));
    }


    /**
     * 获取当前登录用户可控微信号的好友列表
     * @return array|null
     */
    public function getContacts()
    {
        $user = request()->user();  //获取当前登录用户信息
        $groups = $user->group->getLeafBy($user->group_id);
        if (is_null($groups)) return null;
        if (is_array($groups)) {
            $group_id = array_map(function ($v) {
                return $v['_id'];
            }, $groups);
        } else {
            $group_id = [$groups->_id];
        }
        $projects = Project::whereIn('group_id', $group_id)->get(['title', 'wx_id']);
        $project_wx = $projects->pluck('wx_id', 'id')->all();
        $data = [];
        foreach ($project_wx as $project_id => $wx_id) {
            foreach ($wx_id as $id) {
                $client = WxClient::find($id);
                if (is_null($client)) return null;
                $client = $client->toArray();
                $contact = $this->getCustomer($client, $user);
                $data[$id] = $contact;
            }
        }
        $total = 0;
        foreach ($data as $key) {
            $total += count($key);
        }
        return compact('total', 'data');
    }

    /**
     * 获取Customer信息
     * @param $client
     * @param $user
     * @return array
     */
    public function getCustomer($client, $user)
    {
        $contacts = [];
        foreach ($client['contacts'] as $key => $customer) {
            $result = Customer::find($customer['customer_id']);
            $acceptors = AcceptRecord::where('customers', $customer['customer_id'])->get();
            $userIds = $acceptors->pluck('user_id')->all();
            $customer['name'] = $result->getAttribute('baseInfo.name');
            $customer['gender '] = $result->getAttribute('baseInfo.gender');
            $customer['acceptors'] = $userIds;
            $groups = $user->group->genTreeBy($user->group_id);
            if (!$groups['children']) {
                $customers = AcceptRecord::where('user_id', $user->id)->first();
                if (in_array($customer['customer_id'], $customers->customers)) {
                    if (!is_null($customer)) {
                        array_push($contacts, $customer);
                    }
                }
            } else {
                if (!is_null($customer)) {
                    array_push($contacts, $customer);
                }
            }

        }
        return $contacts;
    }

    /**
     * 获取用戶有没有权限查看此微信消息
     * @param $wxId
     * @return bool
     */
    public function getWxId($wxId)
    {
        $user = request()->user();  //获取当前登录用户信息
        $projects = Project::where('users', $user->id)->get(['wx_id']);
        $project_wx = $projects->pluck('wx_id', 'id')->all();
        foreach ($project_wx as $project_id => $wx_id) {
            if (in_array($wxId, $wx_id)) {
                return false;
            } else {
                return true;
            }
        }
    }

    /**
     * 获取历史群发消息列表
     * @return mixed
     */
    public function getMessageGroupsList()
    {
        $user = request()->user();  //获取当前登录用户信息
        $clientUins = $this->getClientsUin();
        $messageGroupsList = MessageLog::where(['isGroup' => true, 'user_id' => $user->id])->whereIn('clientUin', $clientUins)->orderBy('_id', 'DESC')->paginate(20);
        return $messageGroupsList;
    }

    public function getPluginNameById($id)
    {
        $client = WxClient::find($id);
        if (!is_null($client)) {
            $plugin = $client->company->plugin;
            return $plugin ? $plugin->name : '';
        }
        return '';
    }

    /**
     * 判断是否能够通过好友请求
     * @param int $uin
     * @param string $account
     * @return bool
     */
    public function checkVerifyMsg(int $uin, string $account)
    {
        // 根据uin获取wxClient
        /**@var WxClient $client**/
        $client = WxClient::where('uin', $uin)->first();
        if (is_null($client)) return false;
        // 检查是否需要使用插件
        $plugin = resolve('App\Plugin');
        $alias = $client->company->getAttribute('alias') ?? '';
        // 插件存在，并且含有'checkVerifyMsg'方法
        if ($plugin && $plugin::alias === $alias // uin指定的client是此域名下的client
            && method_exists($plugin, __FUNCTION__)) {
            return call_user_func_array([$plugin, __FUNCTION__], [$client, $account]);
        }

        return $client->canAddContactByAccount($account); // 默认没有验证，直接返回允许
    }
}